#include <Arduino.h>
//#include <SoftwareSerial.h>  // 软串口库（用于ZW101通信）
#include <WiFi.h>
#include <WebServer.h>
#include <ESPmDNS.h>
#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include "Flash.h"
#include <HardwareSerial.h>

#define HLK_DEBUG //打开日志打印

// ===================== ZW101指纹模块配置 =====================
// 定义指纹模组的UART引脚
#define FINGERPRINT_RX 16  // GPIO16（ZW101 RX ← ESP TX）
#define FINGERPRINT_TX 17  // GPIO17（ZW101 TX → ESP RX）
//SoftwareSerial fingerprintSerial(FINGERPRINT_RX, FINGERPRINT_TX);  // 软串口：(接收脚, 发送脚)

#define touchCtrl 35

// OLED显示屏配置
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_RESET     -1
#define SCREEN_ADDRESS 0x3C
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

// 按钮引脚定义
#define BUTTON_EXIT 33
#define BUTTON_UP 25
#define BUTTON_DOWN 27
#define BUTTON_ENTER 26
#define BUTTON 0

// 按钮状态变量
unsigned long lastButtonPress = 0;
bool buttonPressed = false;
bool buttonPressed_up = false;
bool buttonPressed_enter = false;
bool buttonPressed_down = false;
bool buttonPressed_exit = false;
int clickCount = 0;
bool pressDisplayState = false;
#define DEBOUNCE_TIME 50          // 按钮消抖
#define MULTI_CLICK_INTERVAL 600  // 五次点击的时间窗口(毫秒)
#define REQUIRED_CLICKS 10         // 需要10次点击清除指纹

// 电源控制引脚
#define OLED_POWER 14
#define FINGER_POWER 12

// 全局变量
SYS_INFO sys_info;
PWD_INFO pwd_info;
int current_display_index = 0;  // 当前显示的密码索引
int display_mode = 0;  

WebServer server(80);

const String html_head = "<!DOCTYPE ><html ><head><title>密码库</title><meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" /><meta name=\"viewport\" content=\"width=device-width, minimum-scale=1.0, maximum-scale=1.0\">";
const String html_css_1 = "<style>#myInput {background-image: url(\"\");background-position: 10px 12px; background-repeat: no-repeat; width: 100%;font-size: 16px;padding: 12px 20px 12px 40px;border: 1px solid #ddd;margin-bottom: 12px; }h2 {text-align: center;}";
const String html_css_2 = "table {table-layout: fixed;word-wrap:break-word;border-collapse: collapse; width: 100%; border: 1px solid #ddd;font-size: 18px; }th, td {text-align: left;padding: 12px;}tr {border-bottom: 1px solid #ddd; }tr.header, tr:hover {background-color: #f1f1f1;}.section {margin: 7px auto;box-shadow: 0 2px 3px rgba( 0, 0, 0, .4 );overflow: hidden;-webkit-transition: .35s;transition: .35s;}button.accordion {background: #00C37E;color: #228;  cursor: pointer;padding: 18px;width: 100%;border: none;text-align: left;outline: none;font-size: 15px;transition: 0.4s;}button.accordion.active, button.accordion:hover {background-color: #f19790;}button.accordion:after {content: \"\\002B\";color: #777;font-weight: bold;float: right;margin-left: 5px;}button.accordion.active:after {content: \"\\2212\";}div.panel {padding: 2 6px;background-color: rgba(182, 216, 209, 0.74);max-height: 4px;overflow: hidden;transition: max-height 0.2s ease-out;}";
const String html_css_3 = ".basic-grey {margin-left: auto;margin-right:auto;max-width: 500px;background: #F7F7F7;padding: 25px 15px 25px 10px;font: 12px Georgia, \"Times New Roman\", Times, serif;color: #888;text-shadow: 1px 1px 1px #FFF;border:1px solid #E4E4E4;}.basic-grey h2 {font-size: 25px;padding: 0px 0px 10px 40px;display: block;border-bottom:1px solid #E4E4E4;margin: -10px -15px 30px -10px;;color: #888;}.basic-grey h2>span {display: block;font-size: 8px;}.basic-grey label {display: block;margin: 0px;}.basic-grey label>span {float: left;width: 20%;text-align: right;padding-right: 10px;margin-top: 10px;color: #888;}.basic-grey input[type=\"text\"], .basic-grey input[type=\"email\"],.basic-grey input[type=\"password\"], .basic-grey textarea {border: 1px solid #DADADA;color: #888;height: 30px;margin-bottom: 16px;margin-right: 6px;margin-top: 2px;outline: 0 none;padding: 3px 3px 3px 5px;width: 70%;font-size: 12px;line-height:15px;box-shadow: inset 0px 1px 4px #ECECEC;-moz-box-shadow: inset 0px 1px 4px #ECECEC;-webkit-box-shadow: inset 0px 1px 4px #ECECEC;}.basic-grey textarea{padding: 5px 3px 3px 5px;height:100px;}.basic-grey .button {background: #E27575;border: none;padding: 10px 25px 10px 25px;color: #FFF;box-shadow: 1px 1px 5px #B6B6B6;border-radius: 3px;text-shadow: 1px 1px 1px #9E3F3F;cursor: pointer;}</style>";
const String html_js = "<script type=\"text/javascript\">function fold() {var acc = document.getElementsByClassName(\"accordion\");var i;for (i = 0; i < acc.length; i++) {acc[i].onclick = function() {this.classList.toggle(\"active\");var panel = this.nextElementSibling;if (panel.style.maxHeight){panel.style.maxHeight = null;} else {panel.style.maxHeight = panel.scrollHeight + \"px\";} }}}</script><script type=\"text/javascript\">function search() {var input, filter, table, tr, td, i;input = document.getElementById(\"myInput\");filter = input.value.toUpperCase();table = document.getElementById(\"myTable\");tr = table.getElementsByTagName(\"div\");for (i = 0; i < tr.length; i++) {td = tr[i].getElementsByTagName(\"button\")[0];if (td) {if (td.innerHTML.toUpperCase().indexOf(filter) > -1) {tr[i].style.display = \"\";} else {tr[i].style.display = \"none\";}} }}</script>";
const String html_top = "<body onload=\"fold()\"><h2>密码本</h2><input type=\"text\" id=\"myInput\" onkeyup=\"search()\" placeholder=\"搜索站点...\"><div id=\"myTable\">";
const String html_new = "<div class = \"section\"><button class=\"accordion\"> ●&nbsp;新增密码信息</button><div class=\"panel\"><form method=\"post\" enctype=\"application/x-www-form-urlencoded\" action=\"/\" class=\"basic-grey\"><h2>Password Form<span>Please fill all the texts in the fields.</span></h2><label><span>网址站点*:</span><input type=\"hidden\"  name=\"command\" value=\"1\"><input type=\"text\" name=\"SITE\" placeholder=\"Bilibili\" required=\"\"></label><label><span>用户姓名*:</span><input type=\"text\" name=\"ID\" placeholder=\"爱吃花椒的喵酱\" required=\"\"></label><label> <span>账号密码*:</span><input type=\"password\" name=\"PWD\" placeholder=\"wbb1997bilibli\" required=\"\"></label><label><span>注册电话:</span><input type=\"text\" name=\"PHONE\" placeholder=\"13000000000\" ></label><label><span>注册邮箱:</span><input type=\"email\" name=\"EMAIL\" placeholder=\"100000@qq.com\" ></label><label><span>关联信息:</span><input type=\"text\" name=\"LINK\" placeholder=\"绑定微信\" ></label><label><span>备注信息:</span><textarea name=\"TIPS\" placeholder=\"这是大号\" ></textarea></label><label><span>&nbsp;</span><input type=\"submit\" class=\"button\" value=\"Submit\"></label></form>  </div></div>";
const String html_confirm_1 = "<div class = \"section\"><button class=\"accordion\"> ●&nbsp;修改系统消息</button><div class=\"panel\"><form method=\"post\" enctype=\"application/x-www-form-urlencoded\" action=\"/\" class=\"basic-grey\"><h2>Set System Info<span>Please fill your original password in the fields.</span></h2><label><span>登陆密码:</span><input type=\"hidden\"  name=\"command\" value=\"4\"><input type=\"password\" name=\"WWW_PWD\" placeholder=\"你的登录密码\" required=\"\"></label><label><span>&nbsp;</span><input type=\"submit\" class=\"button\" value=\"Submit\"></label></form> ";
const String html_forget_1 = "<form method=\"post\" enctype=\"application/x-www-form-urlencoded\" action=\"/\" class=\"basic-grey\"><h2>Great!!!<span>You, lost password again! </span><br><span>点击找回密码后五秒钟内按物理按键</span><br><span>提示：长按按键后再通电开机可重置登陆用户密码，长点记性</span><br></h2><label><input type=\"hidden\"  name=\"command\" value=\"5\"></label><label><span>&nbsp;</span><input type=\"submit\" class=\"button\" value=\"忘记登陆密码\"></label></form>";
const String html_forget_2 = "<form method=\"post\" enctype=\"application/x-www-form-urlencoded\" action=\"/\" class=\"basic-grey\"><h2>Great!!!<span>You, lost password again! </span><br><span>没有办法咯，不断重复试一试你的常用的6位数字密码</span><br><span>实在不行只能找密码本制作人重置密码了</span><br></h2></form>";
const String html_confirm_2 = "</div></div>";

const String html_setting_1 = "<div class = \"section\"><button class=\"accordion\">修改系统消息</button><div class=\"panel\"><form method=\"post\" enctype=\"application/x-www-form-urlencoded\" action=\"/\" class=\"basic-grey\"><h2>Modify System Setting Form<span>Please fill all the texts in the fields.</span></h2><label><span>WIFI名称*:</span><input type=\"hidden\"  name=\"command\" value=\"0\"><input type=\"text\" name=\"WIFI_ID\" placeholder=\"";
const String html_setting_1_init = "<div class = \"section\"><button class=\"accordion\">嗨~别来无恙</button><div class=\"panel\"><form method=\"post\" enctype=\"application/x-www-form-urlencoded\" action=\"/\" class=\"basic-grey\"><h2>Hello~ Welcome to Password Book<span>Please initialize all of the following information</span></h2><label><span>WIFI名称*:</span><input type=\"hidden\"  name=\"command\" value=\"0\"><input type=\"text\" name=\"WIFI_ID\" placeholder=\"";
const String html_setting_2 = "\" required=\"\"></label><label><span>WIFI密码*:</span><input type=\"password\" name=\"WIFI_PWD\" placeholder=\"";
const String html_setting_3 = "\" required=\"\"></label><label><span>登陆名称*:</span><input type=\"text\" name=\"WWW_ID\" placeholder=\"";
const String html_setting_4 = "\" required=\"\"></label><label><span>登陆密码*:</span><input type=\"password\" name=\"WWW_PWD\" placeholder=\"";
const String html_setting_5 = "\" required=\"\"></label><label><span>&nbsp;</span><input type=\"submit\" class=\"button\" value=\"Submit\"></label></form>  </div></div>";
const String html_recyc = "<div class = \"section\"> <form action=\"/\" method=\"post\"><div><input type=\"hidden\"  name=\"command\" value=\"3\"><button class=\"accordion\"> ●&nbsp;密码回收站</button></div></form></div>";
const String html_rt = "<div class = \"section\"><a href=\"/\"><button class=\"accordion\"> ●&nbsp;返回密码列表</button><a></div> ";
const String html_section_1 = "<div class = \"section\"><button class=\"accordion\">";
const String html_section_2 = "</button><div class=\"panel\"><table border = \"1\"><tr ><th width=\"30%\" bgcolor=\"#ccccd6\">站点</th><th width=\"70%\" bgcolor=\"#c3d7df\">";
const String html_section_3 = "</th></tr><tr><td bgcolor=\"#ccccd6\">用户</td><td bgcolor=\"#c3d7df\">";
const String html_section_4 = "</td></tr><tr><td bgcolor=\"#ccccd6\">密码</td><td bgcolor=\"#c3d7df\">";
const String html_section_5 = "</td></tr><tr><td bgcolor=\"#ccccd6\">手机</td><td bgcolor=\"#c3d7df\">";
const String html_section_6 = "</td></tr><tr><td bgcolor=\"#ccccd6\">邮箱</td><td bgcolor=\"#c3d7df\">";
const String html_section_7 = "</td></tr><tr><td bgcolor=\"#ccccd6\">关联</td><td bgcolor=\"#c3d7df\">";
const String html_section_8 = "</td></tr><tr><td bgcolor=\"#ccccd6\">备注</td><td bgcolor=\"#c3d7df\">";  
const String html_section_9 = "</td></tr></table>";
const String html_del_1 = "<form action=\"/\" method=\"post\"><div><input type=\"hidden\"  name=\"command\" value=\"2\"><input type=\"hidden\"  name=\"id\" value=\"";
const String html_del_2 = "\"><input type=\"submit\" class=\"button\" value=\"删除本条密码信息\"></div></form>";
const String html_section_end = "</div></div>";

const String html_about = "<div class = \"section\"><button class=\"accordion\">●&nbsp;About关于</button><div class=\"panel\"><h3>关于本站点：</h3><p>程序版本：v2.0<br>作者：skyqin、knyin 由SYP修改 <br>oshwhub：<a href=\"https://baidu.com\">ESP32_PASSWORDBOOK<a><br></p></div></div>";
const String html_tail = "</div></body></html>";

// ===================== ZW101指纹示例 =====================
// 定义指令包格式
const uint8_t HEADER_HIGH = 0xEF;
const uint8_t HEADER_LOW = 0x01;
const uint32_t DEVICE_ADDRESS = 0xFFFFFFFF;

// 定义指令码
const uint8_t CMD_GET_IMAGE = 0x01;  // 获取图像
const uint8_t CMD_GEN_CHAR = 0x02;   // 生成特征
const uint8_t CMD_MATCH = 0x03;   // 精确比对指纹
const uint8_t CMD_SEARCH = 0x04;   // 搜索指纹
const uint8_t CMD_REG_MODEL = 0x05;  // 合并特征
const uint8_t CMD_STORE_CHAR = 0x06; // 存储模板
const uint8_t CMD_CLEAR_LIB = 0x0D;   // 清空指纹库
const uint8_t CMD_READ_SYSPARA = 0x0F; // 读模组基本参数
const uint8_t CMD_HAND_SHAKE = 0x35; // 握手指令，检测模组是否正常工作
const uint8_t CMD_Read_Num = 0x1d; // 读有效模板个数
const uint8_t CMD_Read_AddPara = 0x62; // 删除N个模板


// 定义缓冲区ID
uint8_t BUFFER_ID = 0;

// 定义模板存储位置 
uint16_t TEMPLATE_ID = 0;

bool isyz = false;

int validNum = 0;
int touch_status = 0;

// 函数声明
int read_FP_info(void);
void send_cmd(uint8_t cmd);
void send_cmd2(uint8_t cmd, uint8_t param1 );
void sendCommand(uint8_t cmd, uint8_t param1 = 0, uint16_t param2 = 0);
void sendCommand1(uint8_t cmd, uint8_t param1, uint16_t param2, uint16_t param3);
bool receiveResponse();
void printResponse(uint8_t *response, uint8_t length);
int validTempleteNum(void);
int read_add_para(void);
int search_FP(void);
int addFinger(int num);

void handleNotFound();
void handleRoot();
void handleButtons();
void updateDisplay();
void displayMessage(const String& line1, const String& line2, const String& line3, const String& line4); //显示4行小字体
void displayMessage2(const String& line1, const String& line2);                                          //显示2行大字体
void checkButton();

void load_info();
void oled_on();
void oled_off();
void finger_open();
void finger_close();
int read_finger_touch(void);
int fingerInit(void);
int clear_FP_all_lib(void);

void oled_on(){
  digitalWrite(OLED_POWER , HIGH);
}

void oled_off(){
  digitalWrite(OLED_POWER , LOW);
}

void finger_open(){
  digitalWrite(FINGER_POWER , HIGH);
}

void finger_close(){
  digitalWrite(FINGER_POWER , LOW);
}

int read_finger_touch(){
    return digitalRead(touchCtrl);
}

void printHex(uint8_t* data, uint8_t len) {
  for(uint8_t i=0; i<len; i++){
    if(data[i] < 0x10) Serial.print('0');
    Serial.print(data[i], HEX);
    Serial.print(' ');
  }
  Serial.println();
}

// ===================== ZW101指纹模块核心函数 =====================
// 1. 发送指令到ZW101并获取响应（基础通信函数）
//读模组基本参数
int read_FP_info(void)
{
  uint8_t response[32];
  uint8_t index = 0;
  uint32_t startTime = millis();
  
  Serial.println("ZW101 FPM info:");
  send_cmd(CMD_READ_SYSPARA);
  
  // 等待响应包
  while (millis() - startTime < 2000) {
    if (Serial2.available()) {
      response[index++] = Serial2.read();
      if (index >= 28) break;
    }
  }

  // 打印响应包
  // printResponse(response, index);

  // 检查确认码
  if (index >= 28 && response[9] == 0x00) {
    uint16_t register_cnt = (uint16_t)(response[10]<<8) | response[11];
    uint16_t fp_temp_size = (uint16_t)(response[12]<<8) | response[13];
    uint16_t fp_lib_size  = (uint16_t)(response[14]<<8) | response[15];
    uint16_t score_level  = (uint16_t)(response[16]<<8) | response[17];
    uint32_t device_addr  = (uint32_t)(response[18]<<24) | (response[19]<<16)| (response[20]<<8) | response[21];
    uint16_t data_pack_size = (uint16_t)(response[22]<<8) | response[23];
    if(0 == data_pack_size) {
      data_pack_size = 32;
    }
    else if(1 == data_pack_size) {
      data_pack_size = 64;
    }
    else if(2 == data_pack_size) {
      data_pack_size = 128;
    }
    else if(3 == data_pack_size) {
      data_pack_size = 256;
    }
    uint16_t baud_set = (uint16_t)(response[24]<<8) | response[25];
    
    Serial.print("register cnt:");
    Serial.println(register_cnt);
    Serial.print("temp size:0x");
    Serial.println(fp_temp_size,HEX);
    Serial.print("lib size:");
    Serial.println(fp_lib_size);
    Serial.print("level:");
    Serial.println(score_level);
    Serial.print("devece address:0x");
    Serial.println(device_addr,HEX);
    Serial.print("data size:");
    Serial.println(data_pack_size);
    Serial.print("baud:");
    Serial.println(baud_set*9600);
    Serial.println("ZW101 init successed");
    return (register_cnt);  // 成功
  } else {
    Serial.println("ZW101 init failed, status: ");
    return 0; // 失败
  }
  
}

// 2. 初始化ZW101模块
//检测模组是否正常工作
int fingerInit(void)
{
  
  delay(500);
  send_cmd(CMD_HAND_SHAKE);
  // 等待指纹模组响应
    if (receiveResponse()) {
      
      return true;
    } else {
      
      return false;
    }
  
}

// 3. 读取有效模板个数
int validTempleteNum(void)
{
  
  send_cmd(CMD_Read_Num);
  uint8_t response[50];
  uint8_t index = 0;
  uint32_t startTime = millis();
  
  // 等待响应包
  while (millis() - startTime < 500) {
    if (Serial2.available()) {
      response[index++] = Serial2.read();
    }
  }

  // 打印响应包
#if defined(HLK_DEBUG)
  printResponse(response, index);
#endif

  // 检查确认码
  if (index >= 12 && response[9] == 0x00) {
    uint16_t result = (uint16_t)(response[10]<<8) | response[11];
    Serial.print("有效指纹模板个数：");
    Serial.println(result);
    return (result);  // 成功
  }else {
    return (0);
  } 
  
}

//读取模组附加参数CMD_Read_AddPara
int read_add_para(void)
{
  
  send_cmd(CMD_Read_AddPara);
  uint8_t response[50];
  uint8_t index = 0;
  uint32_t startTime = millis();
  
  // 等待响应包
  while (millis() - startTime < 500) {
    if (Serial2.available()) {
      response[index++] = Serial2.read();
    }
  }

  // 打印响应包
#if defined(HLK_DEBUG)
  printResponse(response, index);
#endif

  // 检查确认码
  if (index >= 12 && response[9] == 0x00) {
    Serial.print("模组附加参数：");
    Serial.print((response[10]<<8) | response[11],HEX);
    Serial.print(' ');
    Serial.print((response[12]<<8) | response[13],HEX);
    Serial.print(' ');
    Serial.print((response[14]<<8) | response[15],HEX);
    Serial.print(' ');
    Serial.println((response[16]<<8) | response[17],HEX);
    return (1);  // 成功
  }else {
    return (0);
  } 
  
}

// 6. 删除所有指纹（返回状态：0=成功，1=失败）
//清空指纹库
int clear_FP_all_lib(void)
{
  
  send_cmd(CMD_CLEAR_LIB);
  if (receiveResponse()) {
    return 1;
  }
  return 0;
  
}

// ===================== ZW101指纹模块发送指令函数 =====================
// 发送指令包send_cmd
void send_cmd(uint8_t cmd) {
  uint8_t packet[12];
  uint16_t length=3;
  uint16_t checksum =  1+length+cmd;

  // 构建指令包
  packet[0] = HEADER_HIGH;
  packet[1] = HEADER_LOW;
  packet[2] = (DEVICE_ADDRESS >> 24) & 0xFF;
  packet[3] = (DEVICE_ADDRESS >> 16) & 0xFF;
  packet[4] = (DEVICE_ADDRESS >> 8) & 0xFF;
  packet[5] = DEVICE_ADDRESS & 0xFF;
  packet[6] = 0x01;  // 包标识：命令包
  packet[7] = (length >> 8) & 0xFF;  // 包长度高字节
  packet[8] = length & 0xFF;  // 包长度低字节
  packet[9] = cmd;
  
  packet[10] = (checksum >> 8) & 0xFF;
  packet[11] = checksum & 0xFF;

#if defined(HLK_DEBUG)
  Serial.println("send1:");
  printHex(packet,(2+4+3+length));
#endif

  // 发送指令包
  for (int i = 0; i < (2+4+3+length); i++) {
    Serial2.write(packet[i]);
  }
  
}
// 发送指令包send_cmd2
void send_cmd2(uint8_t cmd, uint8_t param1 ) {
  uint8_t packet[13];
  uint16_t length=4;
  uint16_t checksum =  1+length+cmd + param1;

  // 构建指令包
  packet[0] = HEADER_HIGH;
  packet[1] = HEADER_LOW;
  packet[2] = (DEVICE_ADDRESS >> 24) & 0xFF;
  packet[3] = (DEVICE_ADDRESS >> 16) & 0xFF;
  packet[4] = (DEVICE_ADDRESS >> 8) & 0xFF;
  packet[5] = DEVICE_ADDRESS & 0xFF;
  packet[6] = 0x01;  // 包标识：命令包
  packet[7] = (length >> 8) & 0xFF;  // 包长度高字节
  packet[8] = length & 0xFF;  // 包长度低字节
  packet[9] = cmd;
  packet[10] = param1;
  packet[11] = (checksum >> 8) & 0xFF;
  packet[12] = checksum & 0xFF;

#if defined(HLK_DEBUG)
  Serial.println("send2:");
  printHex(packet,(2+4+3+length));
#endif

  // 发送指令包
  for (int i = 0; i < (2+4+3+length); i++) {
    Serial2.write(packet[i]);
  }

}

// 发送指令包sendCommand
void sendCommand(uint8_t cmd, uint8_t param1, uint16_t param2) {
  uint8_t packet[15];
  uint16_t length=6;
  uint16_t checksum =  1+length+cmd + param1 + (param2 >> 8) + (param2 & 0xFF);

  // 构建指令包
  packet[0] = HEADER_HIGH;
  packet[1] = HEADER_LOW;
  packet[2] = (DEVICE_ADDRESS >> 24) & 0xFF;
  packet[3] = (DEVICE_ADDRESS >> 16) & 0xFF;
  packet[4] = (DEVICE_ADDRESS >> 8) & 0xFF;
  packet[5] = DEVICE_ADDRESS & 0xFF;
  packet[6] = 0x01;  // 包标识：命令包
  packet[7] = (length >> 8) & 0xFF;  // 包长度高字节
  packet[8] = length & 0xFF;  // 包长度低字节
  packet[9] = cmd;
  packet[10] = param1;
  packet[11] = (param2 >> 8) & 0xFF;
  packet[12] = param2 & 0xFF;
  packet[13] = (checksum >> 8) & 0xFF;
  packet[14] = checksum & 0xFF;

#if defined(HLK_DEBUG)
  Serial.println("send:");
  printHex(packet,(2+4+3+length));
#endif

  // 发送指令包
  for (int i = 0; i < (2+4+3+length); i++) {
    Serial2.write(packet[i]);
  }
}

// 发送指令包sendCommand1
void sendCommand1(uint8_t cmd, uint8_t param1, uint16_t param2, uint16_t param3) {
  uint8_t packet[17];
  uint16_t length=8;
  uint16_t checksum =  1+length+cmd + param1 + (param2 >> 8) + (param2 & 0xFF) + (param3 >> 8) + (param3 & 0xFF);

  // 构建指令包
  packet[0] = HEADER_HIGH;
  packet[1] = HEADER_LOW;
  packet[2] = (DEVICE_ADDRESS >> 24) & 0xFF;
  packet[3] = (DEVICE_ADDRESS >> 16) & 0xFF;
  packet[4] = (DEVICE_ADDRESS >> 8) & 0xFF;
  packet[5] = DEVICE_ADDRESS & 0xFF;
  packet[6] = 0x01;  // 包标识：命令包
  packet[7] = (length >> 8) & 0xFF;  // 包长度高字节
  packet[8] = length & 0xFF;  // 包长度低字节
  packet[9] = cmd;
  packet[10] = param1;
  packet[11] = (param2 >> 8) & 0xFF;
  packet[12] = param2 & 0xFF;
  packet[13] = (param3 >> 8) & 0xFF;
  packet[14] = param3 & 0xFF;
  packet[15] = (checksum >> 8) & 0xFF;
  packet[16] = checksum & 0xFF;

#if defined(HLK_DEBUG)
  Serial.println("send:");
  printHex(packet,(2+4+3+length));
#endif

  // 发送指令包
  for (int i = 0; i < (2+4+3+length); i++) {
    Serial2.write(packet[i]);
  }
}

// 接收响应包
bool receiveResponse() {
  uint8_t response[50];
  uint8_t index = 0;
  uint32_t startTime = millis();

  // 等待响应包
  while (millis() - startTime < 800) {
    if (Serial2.available()) {
      response[index++] = Serial2.read();
    }
  }

  // 打印响应包
#if defined(HLK_DEBUG)
  printResponse(response, index);
#endif

  // 检查确认码
  if (index >= 12 && response[9] == 0x00) {
    return true;  // 成功
  } else {
    return false; // 失败
  }
}

// 打印响应包
void printResponse(uint8_t *response, uint8_t length) {
  Serial.print("Response:");
  for (int i = 0; i < length; i++) {
    if(response[i] < 0x10) Serial.print('0');
    Serial.print(response[i], HEX);
    Serial.print(" ");
  }
  Serial.println();
}


// ===================== 初始化（新增指纹模块初始化） =====================
void setup(void) {
    Serial.begin(115200);
    //Serial2.begin(57600);
    //Serial2.begin(57600,SERIAL_8N1,FINGERPRINT_RX,FINGERPRINT_TX);
    for (uint8_t t = 3; t > 0; t--) {
        Serial.printf("[SETUP] WAIT %d...\n", t);
        Serial.flush();
        delay(1000);
    }
    
    // 初始化电源控制引脚
    pinMode(OLED_POWER, OUTPUT);
    pinMode(FINGER_POWER, OUTPUT);
    pinMode(touchCtrl , INPUT);
    Serial.println("初始化引脚成功");
    delay(1000);
    
    // 开启OLED和指纹模块电源
    oled_on();
    finger_open();
    Serial.println("开启OLED和指纹电源");
    delay(1000);

    // 初始化OLED显示屏
    Wire.begin(21, 22);  // SDA=21, SCL=22
    if(!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) {
        Serial.println(F("SSD1306 显示屏参数错误！"));
        //for(;;);
    }   
    display.display();
    Serial.println(F("OLED初始化结束"));
    delay(1000);
    
      // 初始化按钮引脚
    pinMode(BUTTON_EXIT, INPUT);
    pinMode(BUTTON_UP, INPUT);
    pinMode(BUTTON_DOWN, INPUT);
    pinMode(BUTTON_ENTER, INPUT);
    pinMode(BUTTON, INPUT);
    digitalWrite(BUTTON_EXIT,LOW);
    digitalWrite(BUTTON_UP,LOW);
    digitalWrite(BUTTON_DOWN,LOW);
    digitalWrite(BUTTON_ENTER,LOW);
    
    Serial.println("按钮初始化结束");
    displayMessage2("-INIT BTN-"," SUCCESSED");
    delay(2000);

    // 初始化指纹模块（提前初始化，确保后续检查有效）
    Serial.println("开始初始化指纹模块");
    Serial2.begin(57600,SERIAL_8N1,FINGERPRINT_RX,FINGERPRINT_TX);
    delay(200);
    if (!fingerInit()){
        
        displayMessage2("  Finger"," !!ERROR!!");
        Serial.println("指纹模块检测失败");
        delay(2000);
        //指纹模块故障
        ESP.restart();
    }

    // 初始化NVS
    nvs_init(sys_info, pwd_info);
    displayMessage2("-INIT NVS-"," SUCCESSED");
    Serial.println("NVS初始化结束");
    delay(2000);
    
    displayMessage2("F-P System","Starting..");
      
    //read_FP_info();

    //如果指纹数量为0，则先进入添加指纹的步骤
    validNum = validTempleteNum();
    if (validNum ==0){
        addFinger(validNum);
    }
    
    finger_close();
    //read_add_para();
  
}
  
void loop(void){
  if (!isyz)
  { //首次开机先验证才能继续使用
       
    if(read_finger_touch()){
      finger_open();
      if (search_FP()){
        Serial.println("找到指纹");
        isyz = true;
        displayMessage("","","","");
        load_info();
        if(digitalRead(BUTTON) == 0){//mine is default high
          Serial.println("重置登录密码");
          strcpy(sys_info.www_pwd , "123456");
          save_sys(sys_info);
        }
        Serial.print("Setting soft-AP ... ");
  
        IPAddress softLocal(192,168,4,1);   
        IPAddress softGateway(192,168,4,1);
        IPAddress softSubnet(255,255,255,0);
  
        WiFi.softAPConfig(softLocal, softGateway, softSubnet);  
 
        WiFi.softAP(sys_info.wifi_ssid, sys_info.wifi_pwd, 2, 0, 1);
  
        IPAddress myIP = WiFi.softAPIP();
        Serial.print("AP IP address: ");
        Serial.println(myIP);
  
        
        if (MDNS.begin("esp8266")) {
          Serial.println("MDNS responder started");
        }

        server.on("/", handleRoot);
  
        server.onNotFound(handleNotFound);

        server.begin();
        Serial.println("HTTP服务已启动");

      }else{
        Serial.println("指纹验证失败，不能使用");

        delay(2000);
        return;
      }

    }
    delay(100);
    
  }else
  { // 指纹已验证可以使用
    //Serial.println("允许使用");
    
    finger_close();
    checkButton();
    if (buttonPressed == false & buttonPressed_up == false & buttonPressed_enter == false & buttonPressed_down == false & buttonPressed_exit == false){
      displayMessage2("","Starting..");
    }
    
    //handleButtons();
    server.handleClient();
  }

}


//搜索指纹
int search_FP(void)
{
  
  int serch_cnt = 0; 
  BUFFER_ID = 1;
  while(serch_cnt <= 5) {
    // 步骤1：获取图像
    send_cmd(CMD_GET_IMAGE);
  
    // 等待指纹模组响应
    if (receiveResponse()) {

    } else {
      delay(1000);
      continue;
    }
  
    // 步骤2：生成特征
    send_cmd2(CMD_GEN_CHAR, BUFFER_ID);
    if (receiveResponse()) {
      break;
    } else {
      serch_cnt++;
      delay(500);
      continue;
    }
  }

  // 步骤3：搜索指纹
  BUFFER_ID = 1;
  sendCommand1(CMD_SEARCH, BUFFER_ID, 1, 10);
  if (receiveResponse()) {
    return 1;
  }
  return 0;
  
}

int addFinger(int num)
{
  TEMPLATE_ID = num;
  touch_status = 1;
  BUFFER_ID = 1;
  while(BUFFER_ID <= 5) {
    // 步骤1：获取图像
    
    Serial.print("获取指纹图像5次，第");
    Serial.print(BUFFER_ID);
    Serial.println("次");
    Serial.print("请按下指纹,不要放开！");
    displayMessage(" Get finger image 5T","    This is   " + String(BUFFER_ID) ,"","     Do not move");
    
    if (read_finger_touch()){
      if (touch_status){
        send_cmd(CMD_GET_IMAGE);
        touch_status = 0;
      }
      

    } 
    
    // 等待指纹模组响应
    if (receiveResponse()) {
      
      Serial.println("请放开");
      displayMessage2("Please move","Your finge");
    } else {
      if (!read_finger_touch()) touch_status = 1;
      delay(1000);
      
      continue;
    }
        
    // 步骤2：生成特征
    Serial.println("生成特征中");
    send_cmd2(CMD_GEN_CHAR, BUFFER_ID);
    if (receiveResponse()) {
      BUFFER_ID++;
    } else {
      continue;
    }
    
  }

  // 步骤3：合并特征
  Serial.println("合并特征");
  send_cmd(CMD_REG_MODEL);
  if (receiveResponse()) {
    Serial.println("合并指纹特征成功！");
  } else {
    Serial.println("合并指纹特征失败！");
    return 0;
  }

  // 步骤4：存储模板
  Serial.print("保存指纹到");
  Serial.println(TEMPLATE_ID);
  
  BUFFER_ID = 1;
  sendCommand(CMD_STORE_CHAR, BUFFER_ID, TEMPLATE_ID);
  if (receiveResponse()) {
    Serial.println("指纹保存成功！");
    displayMessage2("Save finge"," SUCCESSED");
    ESP.restart();
  } else {
    Serial.println("指纹保存失败！");
    return 0;
  }
  return 1;
  
}

//pass配置
void load_info(){
  nvs_init(sys_info, pwd_info);
  
  Serial.println("----------- SYS_INFO -----------");
  Serial.println(sys_info.sys_state);
  Serial.println(sys_info.pwd_num);
  Serial.println(sys_info.wifi_ssid);
  Serial.println(sys_info.wifi_pwd);
  Serial.println(sys_info.www_id);
  Serial.println(sys_info.www_pwd);
  Serial.println();

  Serial.println("----------- PWD_INFO -----------");
  Serial.println(pwd_info.site);
  Serial.println(pwd_info.id);
  Serial.println(pwd_info.pwd);
  Serial.println(pwd_info.phone);
  Serial.println(pwd_info.email);
  Serial.println(pwd_info.link);
  Serial.println(pwd_info.tips);
}

void handleRoot() {
    if(server.method() != HTTP_POST && sys_info.sys_state == 0){//init setting
      Serial.println("----------- 进入初始设置页面 -----------");
      
      
      String html = html_head + html_css_1 + html_css_2 + html_css_3 + html_js + html_top ;
      html += html_setting_1_init + String(sys_info.wifi_ssid) + html_setting_2 + " (起码8位)"  + html_setting_3 + String(sys_info.www_id) + html_setting_4 + String(sys_info.www_pwd) + "(6位数,勿忘！)" + html_setting_5 + html_about + html_tail;
      server.send(200, "text/html", html);
      
    }
    else {//normal mode
      Serial.println("----------- NORMAL MODE -----------");
      if(sys_info.sys_state > 0){
        if (!server.authenticate(sys_info.www_id, sys_info.www_pwd))
        return server.requestAuthentication();
      }else{
        sys_info.sys_state++;
        save_sys(sys_info);
      }
      

      if (server.method() != HTTP_POST) {
        Serial.println("----------- 正常显示 -----------");
        
        String html = html_head + html_css_1 + html_css_2 + html_css_3 + html_js + html_top + html_confirm_1;
        #if VERSION == 2
          html += html_forget_2;
        #else
          html += html_forget_1;
        #endif

        html += html_confirm_2 + html_new + html_recyc;
        int index = 0;
        for(int i = 0; i < sys_info.pwd_num; i++){
          if(sys_info.show_flag[i]){
            index++;
            load_pwd(i, pwd_info); 
            html += html_section_1 + String(index) + ". " + String(pwd_info.site) + html_section_2 + String(pwd_info.site) + html_section_3 + String(pwd_info.id) + html_section_4 + String(pwd_info.pwd) + html_section_5 + String(pwd_info.phone) + html_section_6 + String(pwd_info.email) + html_section_7 + String(pwd_info.link)+ html_section_8 + String(pwd_info.tips) + html_section_9 + html_del_1;
            html += String(i) + html_del_2 + html_section_end;
          }
        }
        html += html_about + html_tail;
        server.send(200, "text/html", html);
        
      }else{
        //对于第一个POST参数server.arg(0)
        //0. 修改系统消息 1. 新增 2. 删除  3. 进入回收站页面 4. 进入确认原始密码页面 5. 进入修改设置页面
        if(server.arg(0) == "0"){
          Serial.println("----------- 处理修改设置 -----------");
         
          strcpy(sys_info.www_id , server.arg(3).c_str());
          strcpy(sys_info.www_pwd , server.arg(4).c_str());
          if(sys_info.sys_state == 0)
            sys_info.sys_state = 1;
          if(strcmp(sys_info.wifi_ssid, server.arg(1).c_str()) || strcmp(sys_info.wifi_pwd, server.arg(2).c_str())){
            strcpy(sys_info.wifi_ssid , server.arg(1).c_str());
            strcpy(sys_info.wifi_pwd , server.arg(2).c_str());
            save_sys(sys_info);
            String plain = String("WiFi information has been modified\nPlease connect to the new wifi\n\twifi_ssid: ")+ String(sys_info.wifi_ssid)+ String("\n\twifi_password: ") + String(sys_info.wifi_pwd)+ String("\n\tusr_name: ") + String(sys_info.www_id)+ String("\n\tusr_password: ") + String(sys_info.www_pwd);
            server.send(200, "text/plain", plain);
            delay(1000);
            ESP.restart();
          }else{
            save_sys(sys_info);
            server.send(200, "text/html", "<meta http-equiv=\"refresh\" content=\"0;url=/\">");
          }
          
        }else if(server.arg(0) == "1"){
          Serial.println("----------- 处理新增信息 -----------");
          
          strcpy(pwd_info.site , server.arg(1).c_str());
          strcpy(pwd_info.id , server.arg(2).c_str());
          strcpy(pwd_info.pwd , server.arg(3).c_str());
          strcpy(pwd_info.phone , server.arg(4).c_str());
          strcpy(pwd_info.email , server.arg(5).c_str());
          strcpy(pwd_info.link , server.arg(6).c_str());
          strcpy(pwd_info.tips , server.arg(7).c_str());

          save_pwd(sys_info.pwd_num, pwd_info);
          sys_info.show_flag[sys_info.pwd_num] = 1;
          sys_info.pwd_num++;
          
          save_sys(sys_info);

          
          server.send(200, "text/html", "<meta http-equiv=\"refresh\" content=\"0;url=/\">");
          //server.sendHeader("Location","/");
        }else if(server.arg(0) == "2"){
          
          Serial.println("----------- 处理删除信息 -----------");
          uint16_t n = atoi(server.arg(1).c_str());
          Serial.print("获取的编号：");
          Serial.println(n);
          sys_info.show_flag[n] = 0;
          save_sys(sys_info);
          server.send(200, "text/html", "<meta http-equiv=\"refresh\" content=\"0;url=/\">");
          
        }else if(server.arg(0) == "3"){
          Serial.println("----------- 进回收站页面 -----------");
          
          String html = html_head + html_css_1 + html_css_2 + html_css_3 + html_js + html_top + html_rt;
          int index = 0;
          Serial.println("标识情况：");
          Serial.print("    总密码数:");
          Serial.println(sys_info.pwd_num);
          for(int i = 0; i < sys_info.pwd_num; i++){
            Serial.print("    ");
            Serial.print(i);
            Serial.print(" : ");
            Serial.println(sys_info.show_flag[i]);
            if(sys_info.show_flag[i] == 0){
                Serial.print("即将展示：");
                Serial.println(i);
                index++;
                load_pwd(i, pwd_info); 
                html += html_section_1 + String(index) + ". " + String(pwd_info.site) + html_section_2 + String(pwd_info.site) + html_section_3 + String(pwd_info.id) + html_section_4 + String(pwd_info.pwd) + html_section_5 + String(pwd_info.phone) + html_section_6 + String(pwd_info.email) + html_section_7 + String(pwd_info.link)+ html_section_8 + String(pwd_info.tips) + html_section_9 + html_section_end;          
              }
          }
          html +=  html_tail;
          server.send(200, "text/html", html);
          
        }else if(server.arg(0) == "4"){
            Serial.println("----------- 进入修改设置页面 -----------");
            if(server.arg(1) == sys_info.www_pwd){
              
              String html = html_head + html_css_1 + html_css_2 + html_css_3 + html_js + html_top ;
              html += html_setting_1 + String(sys_info.wifi_ssid) + html_setting_2 ;
              html += String(sys_info.wifi_pwd) + String(" (起码8位)") + html_setting_3 + String(sys_info.www_id) + html_setting_4 + String(sys_info.www_pwd) + "(6位数,勿忘！)" + html_setting_5 + html_about + html_tail;
              server.send(200, "text/html", html);
              
            }else{
              server.send(200, "text/html", "<meta http-equiv=\"refresh\" content=\"0;url=/\">");
            }
        }else if(server.arg(0) == "5"){
            Serial.println("---------- 处理重置登录密码 ---------");
            
            
            unsigned long start = millis();
            while(millis()-start < 5000){
              if((millis()-start)%1000 == 0)
                Serial.println(digitalRead(BUTTON));
              if(digitalRead(BUTTON) == 0){//mine is default high
                Serial.println("按下了按键");
                strcpy(sys_info.www_pwd , "123456");
                save_sys(sys_info);
                
                break;
              }
              
            }
            server.send(200, "text/html", "<meta http-equiv=\"refresh\" content=\"0;url=/\">");
            
        }

      }
    }
    

}

void handleNotFound() {
  
  String message = "File Not Found\n\n";
  message += "URI: ";
  message += server.uri();
  message += "\nMethod: ";
  message += (server.method() == HTTP_GET) ? "GET" : "POST";
  message += "\nArguments: ";
  message += server.args();
  message += "\n";
  for (uint8_t i = 0; i < server.args(); i++) {
    message += " " + server.argName(i) + ": " + server.arg(i) + "\n";
  }
  server.send(404, "text/plain", message);
  delay(1000);
  server.send(200, "text/html", "<head><meta http-equiv=\"refresh\" content=\"0;url=\"/\"\"> </head>");
  
}

// 按钮处理函数
void handleButtons() {
    static unsigned long lastDebounceTime = 0;
    static unsigned long debounceDelay = 50;
    
    if ((millis() - lastDebounceTime) < debounceDelay) {
        return;
    }
    
    lastDebounceTime = millis();
    
    if (digitalRead(BUTTON_UP) == HIGH) {

        // 上一条
        if (display_mode == 0) {
            // 列表模式下切换到上一条
            current_display_index--;
            if (current_display_index < 0) {
                current_display_index = sys_info.pwd_num - 1;
            }
            updateDisplay();
        }
    }
    
    if (digitalRead(BUTTON_DOWN) == HIGH) {
        // 下一条
        if (display_mode == 0) {
            // 列表模式下切换到下一条
            current_display_index++;
            if (current_display_index >= sys_info.pwd_num) {
                current_display_index = 0;
            }
            updateDisplay();
        }
    }
    
    if (digitalRead(BUTTON_ENTER) == HIGH) {
        // 进入/退出详情
        display_mode = !display_mode;
        updateDisplay();
    }
    
    if (digitalRead(BUTTON_EXIT) == HIGH) {
        // 退出到列表模式或返回上级
        if (display_mode == 1) {
            display_mode = 0;  // 退出详情模式
        }
        updateDisplay();
    }
}

// 更新显示内容
void updateDisplay() {
    display.clearDisplay();
    display.setTextSize(1);
    display.setTextColor(SSD1306_WHITE);
    
    if (display_mode == 0) {
        // 列表模式
        display.setCursor(0, 0);
        display.println("密码列表:");
        
        int displayCount = (sys_info.pwd_num < 4) ? sys_info.pwd_num : 4;

        for (int i = 0;  i < displayCount; i++) {
            int index = (current_display_index + i) % sys_info.pwd_num;
            if (sys_info.show_flag[index]) {
                load_pwd(index, pwd_info);
                
                display.setCursor(0, 10 + i * 10);
                if (i == 0) {
                    display.print("> ");
                } else {
                    display.print("  ");
                }
                
                // 截断过长的站点名称
                String site = String(pwd_info.site);
                if (site.length() > 14) {
                    site = site.substring(0, 14) + "...";
                }
                display.println(site);
            }
        }
    } else {
        // 详情模式
        load_pwd(current_display_index, pwd_info);
        
        display.setCursor(0, 0);
        display.println("详情:");
        
        display.setCursor(0, 10);
        display.println("站点: " + String(pwd_info.site));
        
        display.setCursor(0, 20);
        display.println("用户: " + String(pwd_info.id));
        
        display.setCursor(0, 30);
        display.println("密码: " + String(pwd_info.pwd));
        
        // 如果信息较多，可以分页显示
        if (String(pwd_info.phone).length() > 0) {
            display.setCursor(0, 40);
            display.println("电话: " + String(pwd_info.phone));
        }
    }
    
    display.display();
}
//显示小字符
void displayMessage(const String& line1, const String& line2, const String& line3, const String& line4) {
    display.clearDisplay();
    display.setTextSize(1);
    display.setTextColor(SSD1306_WHITE);
    
    // 第一行
    display.setCursor(0, 0);
    display.println(line1);
    
    // 第二行
    display.setCursor(0, 16);
    display.println(line2);
    
    // 第三行
    display.setCursor(0, 32);
    display.println(line3);
    
    // 第四行
    display.setCursor(0, 48);
    display.println(line4);
    
    display.display();
}
//显示大字符
void displayMessage2(const String& line1, const String& line2) {
    display.clearDisplay();
    display.setTextSize(2);
    display.setTextColor(SSD1306_WHITE);
    
    // 第一行
    display.setCursor(0, 10);
    display.println(line1);
    
    // 第二行
    display.setCursor(0, 32);
    display.println(line2);
          
    display.display();
}

void checkButton() {
  // IO0按钮按下(低电平)
    int buttonState = digitalRead(BUTTON);
    if (buttonState == LOW && !buttonPressed) {
      buttonPressed = true;
    
      delay(DEBOUNCE_TIME); // 消抖
    
      unsigned long currentTime = millis();
    
      // 检查是否在时间窗口内
      if (currentTime - lastButtonPress < MULTI_CLICK_INTERVAL) {
        clickCount++;
        Serial.print("按键次数: ");
        Serial.print(clickCount);
        Serial.println("，将执行自爆程序，请慎重！");
        displayMessage2("Press "+ String(clickCount) +"/10T","will BOMB!");
      
        if (clickCount >= REQUIRED_CLICKS) {
          Serial.print("检测到");
          Serial.print(REQUIRED_CLICKS); 
          Serial.println("次按键! 开始清除指纹数据...");
          finger_open();
          delay(1000);
          //清除指纹代码
          if (clear_FP_all_lib()){
            Serial.println("清除指纹库成功");
            displayMessage2("cls finger","successed");
          }else{
            Serial.println("清除指纹库失败");
            displayMessage2("cls finger","error!");
          }

          clickCount = 0;
          ESP.restart();
        }
      } else {
        // 新的一系列点击开始
        clickCount = 1;
        Serial.println("检测到首次按键");
        displayMessage2("Press 1/10","will BOMB!");
   
      }
        lastButtonPress = currentTime;
      
    }
    
    if (buttonState == LOW){

    }
    // 按钮释放
    if (buttonState == HIGH && buttonPressed) {
      buttonPressed = false;
      delay(DEBOUNCE_TIME); // 消抖
    }
  
    // 重置点击计数(如果超过时间窗口)
    if (millis() - lastButtonPress > MULTI_CLICK_INTERVAL && clickCount > 0) {
      Serial.println("按键超时，重新计数");
      clickCount = 0;
    
    }
// UP按钮按下(低电平)
  if (digitalRead(BUTTON_UP) == HIGH){
    displayMessage2("BUTTON","UP");
    buttonPressed_up = true;
  }

  if (digitalRead(BUTTON_UP) == LOW){
    
    buttonPressed_up = false;
  }


// down按钮按下(低电平)
  if (digitalRead(BUTTON_DOWN) == HIGH){
    displayMessage2("BUTTON","DOWN");
    buttonPressed_down = true;
  }
  if (digitalRead(BUTTON_DOWN) == LOW){
    
    buttonPressed_down = false;
  }

// enter按钮按下(低电平)
  if (digitalRead(BUTTON_ENTER) == HIGH){
    displayMessage2("BUTTON","ENTER");
    buttonPressed_enter = true;
  }
  if (digitalRead(BUTTON_ENTER) == LOW){
    
    buttonPressed_enter = false;
  }

// exit按钮按下(低电平)
  if (digitalRead(BUTTON_EXIT) == HIGH){
    displayMessage2("BUTTON","EXIT");
    buttonPressed_exit = true;
  }
  if (digitalRead(BUTTON_EXIT) == LOW){
    
    buttonPressed_exit = false;
  }

}